package com.chennan.javabase.domain.juc;

import io.netty.util.concurrent.CompleteFuture;
import jdk.management.resource.internal.inst.SocketOutputStreamRMHooks;
import org.junit.Test;

import java.util.concurrent.*;

/**
 * @author chennan
 * @createTime 2021年11月04日 11:42:00
 */
public class CompletableFutureTest {

    public static void main(String[] args) {
    }

    /**
     * 创建一个完整的CompletableFuture
     */
    @Test
    public void test1(){
        System.out.println("开始了");
        //不是异步的方法
        CompletableFuture<String> cf = CompletableFuture.completedFuture(delayedTask());
        System.out.println("正在执行其他任务");
        System.out.println(cf.isDone());
        //getNow(null)如果完成的结果返回（这显然是这种情况），但否则返回NULL（参数）
        System.out.println(cf.getNow(null));
    }

    /**
     * 2.运行一个简单的异步阶段
     */
    @Test
    public void test2() {
        System.out.println("开始任务");
        //runAsync方法不支持返回值。
        //supplyAsync可以支持返回值。
        CompletableFuture<Void> cf = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread().isDaemon());
            System.out.println(delayedTask());
        });
        System.out.println("执行正常任务");
        //用于等待阻塞
        cf.join();
        System.out.println(cf.getNow(null));
//        delayedTaskLong();
        System.out.println(cf.isDone());
    }

    /**
     * 上一步接下一步执行
     * 1. then，这意味着该阶段的操作在当前阶段正常完成时发生（无例外）。在这种情况下，当前阶段已经完成，值为“ message”。
     * 2. Apply，这意味着返回的阶段将对Function上一个阶段的结果应用a 。
     */
    @Test
    public void test3() {
        CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApply(String::toUpperCase);
        System.out.println(cf.getNow(null));
    }

    /**
     * 异步操作
     */
    @Test
    public void test4(){
        CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApplyAsync(s->{
            delayedTask();
            return s.toUpperCase();
        });
        System.out.println(cf.getNow(null));
        cf.join();
        System.out.println(cf.getNow(null));
    }


    static ExecutorService executorService = Executors.newFixedThreadPool(3, new ThreadFactory() {
        int count = 1;
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "custom-executor-" + count++);
        }
    });
    /**
     * 异步使用自定义线程池
     */
    @Test
    public void test5() {
        CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApplyAsync(s->{
            System.out.println(Thread.currentThread().getName());
            delayedTask();
            return s.toUpperCase();
        },executorService);
        cf.join();
        System.out.println(cf.getNow(null));
    }

    /**
     * 如果下一阶段接受当前阶段的结果，但不需要在计算中返回值（即，其返回类型为void），则Function可以应用a ，而不是应用a Consumer，因此该方法为thenAccept：
     */
    @Test
    public void test6() {
        StringBuilder sb = new StringBuilder();
        CompletableFuture.completedFuture("message").thenAccept(sb::append);
        System.out.println(sb.toString());
    }

    /**
     * 接受的异步
     */
    @Test
    public void test7() {
        StringBuilder sb = new StringBuilder();
        CompletableFuture<Void> message = CompletableFuture.completedFuture("message").thenAcceptAsync(s -> {
            delayedTask();
            sb.append(s);
        });
        //阻塞等待
        message.join();
        System.out.println(sb.toString());
    }

    /**
     *
     */
    @Test
    public void test8() {
        CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApplyAsync(s->{
            delayedTask();
            return s.toUpperCase();
        });
        CompletableFuture<String> exceptionHandler = cf.handle((s, th) -> { return (th != null) ? "message upon cancel" : ""; });
        cf.completeExceptionally(new RuntimeException("completed exceptionally"));
        System.out.println("打印"+cf.isCompletedExceptionally());
        try {
            cf.join();
        } catch(CompletionException ex) { // just for testing
            System.out.println("异常"+ex.getCause().getMessage());
        }
        System.out.println("最后打印"+exceptionHandler.join());
    }

    /**
     * 创建一个阶段，当所有阶段完成时完成
     * @return
     */
    @Test
    public void test9(){
        CompletableFuture<Void> c1 = CompletableFuture.runAsync(()->{
            delayedTask();
            System.out.println("短时延迟完成");
        });
        CompletableFuture<Void> c2 = CompletableFuture.runAsync(()->{
            delayedTaskLong();
            System.out.println("长时延迟完成");
        });

        CompletableFuture.allOf(c1,c2).whenComplete((t,u)->{
            System.out.println("运行成功"+t+u);
        }).exceptionally(e->null).join();
        System.out.println("主线程完成");
    }

    /**
     * 取消计算
     */
    @Test
    public void test10(){
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
            delayedTask();
            int i = 10/0;
            return "44444";
        });

        System.out.println(cf.cancel(true));
//        boolean completedExceptionally = cf.isCompletedExceptionally();
//        System.out.println(completedExceptionally);
        cf.join();
        cf.whenCompleteAsync((t,u)->{
            System.out.println(t+","+u);
        }).exceptionally(e->{
            System.out.println(e.getMessage());
            return e.getMessage();
        });

    }

    /**
     * 将函数应用于两个完成阶段之一的结果
     */
    @Test
    public void test11(){

    }

    @Test
    public void test12(){

    }

    @Test
    public void test13(){

    }

    @Test
    public void test14(){

    }

    @Test
    public void test15(){

    }

    @Test
    public void test16(){

    }
    @Test
    public void test17(){

    }
    @Test
    public void test18(){

    }
    @Test
    public void test19(){

    }
    @Test
    public void test20(){

    }

    public String delayedTask(){
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "完成了";
    }
    public String delayedTaskLong(){
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "完成了";
    }
}
